<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet"
        href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/atom-one-dark.min.css">
    <title>用户信息管理系统</title>
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
            background-color: #f5f7fa;
            color: #333;
            line-height: 1.6;
            padding: 20px;
        }

        .container {
            max-width: 1000px;
            margin: 0 auto;
            background-color: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }

        header {
            background: linear-gradient(135deg, #4b6cb7, #182848);
            color: white;
            padding: 20px;
            text-align: center;
        }

        h1 {
            font-size: 24px;
            margin-bottom: 10px;
        }

        .tabs {
            display: flex;
            border-bottom: 1px solid #eee;
        }

        .tab {
            padding: 12px 20px;
            cursor: pointer;
            transition: all 0.3s;
            font-weight: 500;
        }

        .tab.active {
            border-bottom: 2px solid #4b6cb7;
            color: #4b6cb7;
        }

        .tab:hover {
            background-color: #f9f9f9;
        }

        .tab-content p {
            margin: 10px 0;
        }

        .tab-content ul {
            list-style: none;
            padding-left: 1rem;
        }

        .tab-content ul li {
            margin-bottom: 5px;
        }

        .content {
            padding: 20px;
        }

        .form-group {
            margin-bottom: 15px;
        }

        label {
            display: block;
            margin-bottom: 5px;
            font-weight: 500;
            color: #555;
        }

        input,
        select,
        textarea {
            width: 100%;
            padding: 10px;
            border: 1px solid #ddd;
            border-radius: 4px;
            font-size: 14px;
            transition: border 0.3s;
        }

        input:focus,
        select:focus,
        textarea:focus {
            border-color: #4b6cb7;
            outline: none;
            box-shadow: 0 0 0 2px rgba(75, 108, 183, 0.2);
        }

        .error {
            color: #e74c3c;
            font-size: 12px;
            margin-top: 5px;
        }

        button {
            background-color: #4b6cb7;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 4px;
            cursor: pointer;
            font-size: 14px;
            transition: background-color 0.3s;
        }

        button:hover {
            background-color: #3a5a9c;
        }

        .btn-secondary {
            background-color: #95a5a6;
        }

        .btn-secondary:hover {
            background-color: #7f8c8d;
        }

        .user-list {
            margin-top: 20px;
        }

        .user-card {
            background-color: #f9f9f9;
            border-radius: 4px;
            padding: 15px;
            margin-bottom: 10px;
            border-left: 3px solid #4b6cb7;
            position: relative;
        }

        .user-card h3 {
            margin-bottom: 10px;
            color: #2c3e50;
        }

        .user-card p {
            margin-bottom: 5px;
            font-size: 14px;
        }

        .user-card .actions {
            position: absolute;
            right: 15px;
            top: 15px;
        }

        .user-card .actions button {
            padding: 5px 10px;
            margin-left: 5px;
            font-size: 12px;
        }

        .hidden {
            display: none;
        }

        .form-row {
            display: flex;
            gap: 15px;
            margin-bottom: 15px;
        }

        .form-row .form-group {
            flex: 1;
            margin-bottom: 0;
        }

        .alert {
            padding: 10px 15px;
            border-radius: 4px;
            margin-bottom: 15px;
        }

        .alert-success {
            background-color: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }

        .alert-error {
            background-color: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }

        .user-info {
            background-color: #f8f9fa;
            border-radius: 4px;
            padding: 15px;
            margin-top: 20px;
        }

        .user-info pre {
            background-color: #fff;
            padding: 10px;
            border-radius: 4px;
            border: 1px solid #eee;
            overflow-x: auto;
        }

        .checkbox-text {
            white-space: nowrap;
        }
    </style>
</head>

<body>
    <div class="container">
        <header>
            <h1>用户信息管理系统</h1>
            <p>基于formToObject方法的表单处理实例</p>
        </header>

        <div class="tabs">
            <div class="tab active" data-tab="register">用户注册</div>
            <div class="tab" data-tab="list">用户列表</div>
            <div class="tab" data-tab="about">关于系统</div>
        </div>

        <div class="content">
            <!-- 注册表单 -->
            <div class="tab-content" id="register-content">
                <div id="form-message" class="hidden"></div>

                <form id="register-form">
                    <div class="form-row">
                        <div class="form-group">
                            <label for="username">用户名 <span style="color: #e74c3c">*</span></label>
                            <input type="text" id="username" name="username" required value="lixianqi@xforceplus.com">
                            <div class="error" id="username-error"></div>
                        </div>

                        <div class="form-group">
                            <label for="email">电子邮箱 <span style="color: #e74c3c">*</span></label>
                            <input type="email" id="email" name="email" required value="lixianqi@xforceplus.com">
                            <div class="error" id="email-error"></div>
                        </div>
                    </div>

                    <div class="form-row">
                        <div class="form-group">
                            <label for="password">密码 <span style="color: #e74c3c">*</span></label>
                            <input type="password" id="password" name="password" required value="123456">
                            <div class="error" id="password-error"></div>
                        </div>

                        <div class="form-group">
                            <label for="confirm-password">确认密码 <span style="color: #e74c3c">*</span></label>
                            <input type="password" id="confirm-password" name="confirmPassword" required value="123456">
                            <div class="error" id="confirm-password-error"></div>
                        </div>
                    </div>

                    <div class="form-row">
                        <div class="form-group">
                            <label for="phone">手机号码</label>
                            <input type="tel" id="phone" name="phone" pattern="[0-9]{11}" value="13242422142">
                            <div class="error" id="phone-error"></div>
                        </div>

                        <div class="form-group">
                            <label for="department">所属部门</label>
                            <select id="department" name="department">
                                <option value="">请选择部门</option>
                                <option value="development">研发部</option>
                                <option value="marketing">市场部</option>
                                <option value="operations">运营部</option>
                                <option value="hr">人力资源部</option>
                                <option value="finance">财务部</option>
                            </select>
                        </div>
                    </div>

                    <div class="form-group">
                        <label for="address">地址</label>
                        <textarea id="address" name="address" rows="3"></textarea>
                    </div>

                    <div class="form-group">
                        <label>角色权限</label>
                        <div style="display: flex; gap: 15px;">
                            <label style="display: inline-flex; align-items: center;">
                                <input type="checkbox" name="roles" value="user" checked>
                                <span style="margin-left: 5px;" class="checkbox-text">普通用户</span>
                            </label>
                            <label style="display: inline-flex; align-items: center;">
                                <input type="checkbox" name="roles" value="editor">
                                <span style="margin-left: 5px;" class="checkbox-text">编辑者</span>
                            </label>
                            <label style="display: inline-flex; align-items: center;">
                                <input type="checkbox" name="roles" value="admin">
                                <span style="margin-left: 5px;" class="checkbox-text">管理员</span>
                            </label>
                        </div>
                    </div>

                    <div class="form-group">
                        <button type="submit" id="submit-btn">注册用户</button>
                        <button type="reset" class="btn-secondary" style="margin-left: 10px;">重置表单</button>
                    </div>
                </form>

                <div class="user-info hidden" id="form-data-display">
                    <h3>表单数据对象</h3>
                    <p>通过formToObject方法转换的表单数据：</p>
                    <pre id="form-data-json"></pre>
                </div>
            </div>

            <!-- 用户列表 -->
            <div class="tab-content hidden" id="list-content">
                <h2>已注册用户列表</h2>
                <p>系统中的所有用户信息：</p>

                <div class="user-list" id="user-list">
                    <!-- 用户卡片将通过JavaScript动态生成 -->
                </div>
            </div>

            <!-- 关于系统 -->
            <div class="tab-content hidden" id="about-content">
                <h2>关于本系统</h2>
                <p>本系统是一个基于formToObject方法的用户信息管理系统示例，展示了如何在实际业务场景中使用表单数据处理。</p>

                <h3>核心功能</h3>
                <ul>
                    <li>用户注册与数据验证</li>
                    <li>表单数据转换为JavaScript对象</li>
                    <li>用户数据本地存储与管理</li>
                    <li>表单数据的可视化展示</li>
                </ul>

                <h3>技术实现</h3>
                <p>核心代码实现：</p>
                <pre>
                    <code>
const formToObject = form => Array.from(new FormData(form)).reduce((acc,[k,v]) => ({ ...acc,[k]:v }),{});
                    </code>
                </pre>

                <p>该方法通过FormData API获取表单数据，并使用reduce方法将其转换为普通JavaScript对象，便于后续处理和存储。</p>

                <p>特别说明：本示例使用localStorage进行数据存储，实际生产环境中应使用服务器端存储。</p>
            </div>
        </div>
    </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/highlight.min.js"></script>
    <script>
        hljs.highlightAll(document.querySelectorAll('pre code'));

        // 核心方法：表单转对象
        const formToObject = form => Array.from(new FormData(form)).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {});

        // 增强版formToObject，处理复选框等特殊表单元素
        const enhancedFormToObject = form => {
            const formData = new FormData(form);
            const obj = {};

            // 获取所有表单字段名称
            const fieldNames = new Set();
            for (const [name] of formData) {
                fieldNames.add(name);
            }

            // 处理每个字段
            for (const name of fieldNames) {
                const values = formData.getAll(name);

                // 如果是多值字段（如复选框），返回数组
                if (values.length > 1) {
                    obj[name] = values;
                } else {
                    obj[name] = values[0];
                }
            }

            return obj;
        };

        // DOM元素
        const registerForm = document.getElementById('register-form');
        const formMessage = document.getElementById('form-message');
        const formDataDisplay = document.getElementById('form-data-display');
        const formDataJson = document.getElementById('form-data-json');
        const userList = document.getElementById('user-list');
        const tabs = document.querySelectorAll('.tab');
        const tabContents = document.querySelectorAll('.tab-content');

        // 表单验证
        function validateForm(formData) {
            let isValid = true;
            const errors = {};

            // 清除所有错误信息
            document.querySelectorAll('.error').forEach(el => el.textContent = '');

            // 用户名验证
            if (!formData.username || formData.username.length < 3) {
                errors.username = '用户名至少需要3个字符';
                isValid = false;
            }

            // 邮箱验证
            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
            if (!formData.email || !emailRegex.test(formData.email)) {
                errors.email = '请输入有效的电子邮箱地址';
                isValid = false;
            }

            // 密码验证
            if (!formData.password || formData.password.length < 6) {
                errors.password = '密码至少需要6个字符';
                isValid = false;
            }

            // 确认密码
            if (formData.password !== formData.confirmPassword) {
                errors.confirmPassword = '两次输入的密码不一致';
                isValid = false;
            }

            // 手机号验证（如果有填写）
            if (formData.phone && !/^1[3-9]\d{9}$/.test(formData.phone)) {
                errors.phone = '请输入有效的11位手机号码';
                isValid = false;
            }

            // 显示错误信息
            for (const [field, message] of Object.entries(errors)) {
                const errorElement = document.getElementById(`${field}-error`);
                if (errorElement) {
                    errorElement.textContent = message;
                }
            }

            return isValid;
        }

        // 保存用户数据到localStorage
        function saveUser(userData) {
            // 获取现有用户数据
            let users = JSON.parse(localStorage.getItem('users') || '[]');

            // 生成唯一ID
            userData.id = Date.now().toString();
            userData.createdAt = new Date().toISOString();

            // 添加新用户
            users.push(userData);

            // 保存回localStorage
            localStorage.setItem('users', JSON.stringify(users));

            return userData;
        }

        // 加载并显示用户列表
        function loadUserList() {
            const users = JSON.parse(localStorage.getItem('users') || '[]');
            userList.innerHTML = '';

            if (users.length === 0) {
                userList.innerHTML = '<p>暂无用户数据</p>';
                return;
            }

            users.forEach(user => {
                const userCard = document.createElement('div');
                userCard.className = 'user-card';
                userCard.innerHTML = `
                    <h3>${user.username}</h3>
                    <p><strong>邮箱:</strong> ${user.email}</p>
                    <p><strong>部门:</strong> ${getDepartmentName(user.department) || '未设置'}</p>
                    <p><strong>手机:</strong> ${user.phone || '未设置'}</p>
                    <p><strong>角色:</strong> ${Array.isArray(user.roles) ? user.roles.map(r => getRoleName(r)).join(', ') : getRoleName(user.roles) || '普通用户'}</p>
                    <p><strong>注册时间:</strong> ${new Date(user.createdAt).toLocaleString()}</p>
                    <div class="actions">
                        <button class="btn-secondary" onclick="deleteUser('${user.id}')">删除</button>
                    </div>
                `;
                userList.appendChild(userCard);
            });
        }

        // 删除用户
        function deleteUser(userId) {
            if (confirm('确定要删除此用户吗？')) {
                let users = JSON.parse(localStorage.getItem('users') || '[]');
                users = users.filter(user => user.id !== userId);
                localStorage.setItem('users', JSON.stringify(users));
                loadUserList();
            }
        }

        // 获取部门名称
        function getDepartmentName(code) {
            const departments = {
                'development': '研发部',
                'marketing': '市场部',
                'operations': '运营部',
                'hr': '人力资源部',
                'finance': '财务部'
            };
            return departments[code] || code;
        }

        // 获取角色名称
        function getRoleName(code) {
            const roles = {
                'user': '普通用户',
                'editor': '编辑者',
                'admin': '管理员'
            };
            return roles[code] || code;
        }

        // 显示消息
        function showMessage(message, type = 'success') {
            formMessage.textContent = message;
            formMessage.className = `alert alert-${type}`;
            formMessage.classList.remove('hidden');

            // 5秒后自动隐藏
            setTimeout(() => {
                formMessage.classList.add('hidden');
            }, 5000);
        }

        // 切换标签页
        function switchTab(tabId) {
            // 更新标签状态
            tabs.forEach(tab => {
                tab.classList.toggle('active', tab.dataset.tab === tabId);
            });

            // 更新内容区域
            tabContents.forEach(content => {
                if (content.id === `${tabId}-content`) {
                    content.classList.remove('hidden');
                } else {
                    content.classList.add('hidden');
                }
            });

            // 如果切换到用户列表，刷新列表
            if (tabId === 'list') {
                loadUserList();
            }
        }

        // 事件监听：表单提交
        registerForm.addEventListener('submit', function (e) {
            e.preventDefault();

            // 使用formToObject获取表单数据
            const formData = enhancedFormToObject(this);
            console.log(6666, formData, validateForm(formData))

            // 表单验证
            if (!validateForm(formData)) {
                return;
            }

            // 显示表单数据
            formDataJson.innerHTML = `<code>${JSON.stringify(formData, null, 2)}</code>`;
            hljs.highlightElement(formDataJson)
            formDataDisplay.classList.remove('hidden');


            // 保存用户数据
            const savedUser = saveUser(formData);

            // 显示成功消息
            showMessage(`用户 ${savedUser.username} 注册成功！`);

            // 重置表单
            this.reset();
        });

        // 事件监听：标签切换
        tabs.forEach(tab => {
            tab.addEventListener('click', () => {
                switchTab(tab.dataset.tab);
            });
        });

        // 初始化
        document.addEventListener('DOMContentLoaded', () => {
            // 默认显示注册标签页
            switchTab('register');
        });
    </script>
</body>

</html>